Managing API Keys, Tokens, and Authentication Credentials in Android
Course: Android App Development
Topic: Managing API Keys, Tokens, and Authentication Credentials
Course Link: Android App Development Course
Demo Link: Register for a Course Demo
Website: JustAcademy
1. Introduction
Android applications commonly connect to REST APIs, backend servers, cloud platforms, payment services, and authentication providers. These services may require API keys, access tokens, refresh tokens, session cookies, or other authentication credentials.
Credentials help identify an application or user and determine which resources they can access. If credentials are exposed, attackers may be able to access protected information, misuse APIs, or perform unauthorized operations. Therefore, developers must understand how credentials work, where they should be stored, how they should be transmitted, and when they should be renewed or revoked.
This topic covers credential types, secure storage, HTTPS communication, authentication workflows, token expiration, refresh operations, logout, troubleshooting, and practical Android implementation examples.
2. Learning Objectives
- Understand API keys, access tokens, refresh tokens, ID tokens, and session credentials.
- Differentiate public application identifiers from confidential secrets.
- Understand why hardcoding sensitive credentials is dangerous.
- Learn about Android Keystore and encrypted local storage.
- Send authentication credentials securely with API requests.
- Handle token expiration, renewal, and revocation.
- Implement secure logout and session management.
- Prevent credential leaks through logs, URLs, analytics, and crash reports.
- Build a practical authentication workflow for an Android application.
3. What Are API Keys?
An API key is a value used by an API provider to identify an application, project, or calling client. It may be used for usage tracking, quotas, billing, service restrictions, or access control.
For example, a weather application may request current weather information from a remote service. The provider may require an API key to identify the application making the request.
GET https://api.example.com/weather?city=Mumbai
X-API-Key: YOUR_API_KEY
The exact format depends on the API provider. Some services use a request header, while others specify a different authentication method. Follow the provider's official documentation.
Characteristics of API Keys
- They identify an application, project, or API client.
- They may enforce usage quotas or service restrictions.
- Some keys are designed for public client-side use, while others are confidential.
- A key packaged inside an Android APK may be extracted through reverse engineering.
- Keys should be restricted, monitored, and rotated when necessary.
Important Security Rule
Never assume that a value is secret simply because it is stored in a Kotlin file, XML resource, Gradle configuration, or an obfuscated APK. If the application needs a confidential server-side credential, keep it on a backend server instead of packaging it inside the Android application.
4. What Are Authentication Tokens?
An authentication token is a credential used to represent an authenticated user, client, or authorization grant. A server or identity provider may issue tokens after a successful login or authorization process.
4.1 Access Token
An access token allows an application to request protected resources. It is commonly sent in the HTTP Authorization header.
Authorization: Bearer ACCESS_TOKEN
Access tokens should be treated as sensitive credentials. Anyone who obtains a usable token may be able to access resources permitted by that token until it expires or is revoked.
4.2 Refresh Token
A refresh token is used to obtain a new access token when the current one expires, if the authentication provider supports token renewal. Refresh tokens are often longer-lived and must be protected carefully.
Refresh tokens should never be logged or exposed to unrelated services. Use token rotation and revocation when supported by the identity provider.
4.3 ID Token
An ID token is used by OpenID Connect to communicate authentication information about a user to a client. It may contain claims such as the user's identifier and token expiration time.
An ID token is not automatically interchangeable with an access token. Each token should be used only for its intended purpose and validated according to the provider's requirements.
4.4 Session Cookies
Some applications use session cookies instead of bearer tokens. After authentication, the server creates a session and the application sends the relevant cookie with subsequent requests. Session identifiers must also be treated as sensitive credentials.
5. Difference Between API Keys and Tokens
| Credential |
Purpose |
Typical Use |
Security Concern |
| API key |
Identifies an application or project |
Accessing an API with provider-defined restrictions |
May be extracted from the APK |
| Access token |
Authorizes access to protected resources |
Sending authenticated API requests |
May allow unauthorized access if stolen |
| Refresh token |
Obtains a replacement access token |
Maintaining a session without repeated login |
Can provide extended access if compromised |
| ID token |
Provides authentication claims |
Identifying an authenticated user to a client |
Must be validated and used for its intended purpose |
| Session cookie |
Maintains a server-managed session |
Authenticated web or API requests |
Session theft may permit impersonation |
6. Why Credential Management Is Important
- Account protection: Helps prevent unauthorized access to user accounts.
- Data privacy: Protects private information exchanged with backend services.
- API protection: Reduces unauthorized use of restricted services.
- Cost management: Helps prevent misuse of quota-based or paid APIs.
- Session security: Supports appropriate login, renewal, and logout behavior.
- Incident response: Allows compromised credentials to be revoked or rotated.
7. Common Credential Security Risks
7.1 Hardcoding Credentials
Hardcoding credentials means placing a secret directly in application source code.
// INSECURE EXAMPLE — do not use
const val API_SECRET = "real-secret-value"
const val USER_PASSWORD = "password123"
Hardcoded values can accidentally be committed to source control or extracted from a compiled application. Keep confidential API secrets on a protected backend and use suitable restrictions for client-side keys.
7.2 Storing Credentials in Plain Text
Saving tokens in unprotected files or ordinary preferences may expose them if the device, application data, backup, or debugging environment is compromised. Choose storage based on credential sensitivity and the application's threat model.
7.3 Sending Credentials Over HTTP
Unencrypted HTTP traffic can expose credentials to interception. Use HTTPS for authentication and credential-bearing API requests. Never disable certificate validation to work around connection problems.
7.4 Logging Sensitive Values
// INSECURE EXAMPLE — never log real credentials
Log.d("Auth", "Access token: $accessToken")
Tokens and authorization headers may be captured in Logcat, debugging output, crash reports, or diagnostic tools. Log a generic status message instead.
7.5 Incorrect Token Refresh
Repeatedly refreshing an invalid token can create retry loops, unnecessary requests, and session failures. Implement controlled refresh logic and return the user to the login flow when renewal is no longer possible.
8. Choosing a Credential Storage Strategy
There is no single storage method that makes every credential completely secure on a user-controlled device. Select an approach based on the credential's value, the authentication provider, Android version requirements, and the application's security needs.
| Storage Method |
Recommended Purpose |
Limitation |
| Android Keystore |
Creating and protecting cryptographic keys |
It is not a general-purpose token database |
| Encrypted local storage |
Storing sensitive application data encrypted with a protected key |
Requires correct encryption and key management |
| DataStore or SharedPreferences |
Storing ordinary application preferences |
Plain storage is not appropriate for high-value credentials |
| Identity provider SDK |
Managing supported login and token workflows |
Requires correct provider configuration |
| Backend secret manager |
Storing confidential server-side API keys and secrets |
Requires secure backend access controls |
9. Understanding Android Keystore
Android Keystore provides a system for creating and using cryptographic keys while limiting direct access to their key material. Depending on the device and configuration, keys may receive hardware-backed protection.
Developers can use Keystore-backed keys for encryption, decryption, or signing operations. Sensitive data can then be encrypted before it is written to local storage.
Benefits of Android Keystore
- Helps protect cryptographic key material.
- Supports device-bound cryptographic operations.
- Can support key-use restrictions when available.
- Can be combined with encrypted storage to protect sensitive data.
Important: Keystore does not automatically encrypt arbitrary token strings. The application must use a correct encryption and storage design or rely on an appropriate authentication SDK.
10. Managing API Keys in Android Projects
10.1 Keep Confidential Secrets on the Backend
If a third-party service requires a confidential API key, the recommended architecture is for the Android application to call your backend, which then calls the third-party API using the server-side key.
Android Application
|
| HTTPS request
v
Your Backend Server
|
| Confidential key stays on server
v
Third-Party API
The backend can validate the user, enforce permissions, apply rate limits, and protect the confidential credential.
10.2 Separate Environment Configuration
Development, staging, and production environments should use separate configuration values. Gradle build configuration can help organize non-secret values such as base URLs.
// app/build.gradle.kts
android {
defaultConfig {
buildConfigField(
"String",
"API_BASE_URL",
"\"https://api.example.com\""
)
}
}
This example defines a base URL, which is generally not confidential. Moving a private key into Gradle or BuildConfig does not make it secret if the value is packaged into the APK.
10.3 Restrict and Rotate API Keys
- Restrict keys to the APIs and services that the application needs.
- Use package name and signing-certificate restrictions when supported.
- Apply quotas and monitor usage.
- Keep development and production keys separate.
- Rotate exposed credentials and remove obsolete keys.
- Review provider dashboards for unusual activity.
11. Storing User Authentication Tokens
After login, an application may receive an access token and, depending on the provider, a refresh token. These credentials should not be stored in source code, unprotected files, analytics events, or diagnostic logs.
For production applications, prefer a reputable identity-provider SDK when available. If the application needs its own secure token-storage implementation, use a suitable encrypted-storage approach and protect its encryption key with Android Keystore.
Example: Token Repository Interface
interface TokenRepository {
suspend fun getAccessToken(): String?
suspend fun saveTokens(
accessToken: String,
refreshToken: String?
)
suspend fun clearTokens()
}
This interface separates credential storage from the rest of the application. It does not itself encrypt anything; the implementation must provide the required protection and error handling.
12. Sending Authentication Tokens with API Requests
Retrofit and OkHttp are commonly used in Android applications to communicate with REST APIs. A request interceptor can attach the current access token to requests sent to a trusted API.
class AuthHeaderInterceptor(
private val tokenProvider: () -> String?
) : okhttp3.Interceptor {
override fun intercept(
chain: okhttp3.Interceptor.Chain
): okhttp3.Response {
val original = chain.request()
val token = tokenProvider()
val requestBuilder = original.newBuilder()
if (!token.isNullOrBlank()) {
requestBuilder.header(
"Authorization",
"Bearer $token"
)
}
return chain.proceed(requestBuilder.build())
}
}
This example assumes that tokenProvider can synchronously return the current access token. Configure the interceptor only for the intended API host. Never send a bearer token automatically to unrelated websites or third-party domains.
Important Implementation Notes
- Keep network requests off the main thread.
- Do not log the Authorization header.
- Ensure that token access and updates are thread-safe.
- Do not use an expired token indefinitely.
- Follow the backend's documented authentication requirements.
13. Handling Token Expiration
Access tokens usually have a limited lifetime. When a token expires or becomes invalid, a server may return HTTP 401 Unauthorized. The application should follow the API provider's documented behavior rather than assuming every 401 response requires a refresh.
Recommended Token Lifecycle
- The user authenticates through the approved login flow.
- The application receives an access token and possibly a refresh token.
- The application sends the access token with protected API requests.
- The server rejects an expired or invalid token.
- The application refreshes the token if the provider supports it and the failure is appropriate for refresh.
- The application securely saves the replacement credentials.
- The original request is retried only when safe and appropriate.
- If refresh fails, the application clears invalid session state and asks the user to sign in again.
Illustrative Kotlin Pseudocode
suspend fun getUsableAccessToken(): String? {
val current = tokenRepository.getAccessToken()
if (current != null && !isKnownToBeExpired(current)) {
return current
}
// Placeholder: use the provider's documented refresh flow.
return authenticationService.refreshAccessToken()
}
The functions in this example are illustrative and are not built-in Android APIs. The server remains responsible for validating tokens and enforcing authorization, even if the client checks expiration locally.
14. Preventing Concurrent Token Refresh Problems
If several API requests fail simultaneously, each request may attempt to refresh the same token. This can cause unnecessary requests and may break authentication systems that rotate refresh tokens.
Recommended practices include:
- Coordinate refresh operations so only one refresh is active at a time.
- Let waiting requests reuse the refreshed access token.
- Update related credentials consistently.
- Set a retry limit and prevent infinite loops.
- Avoid automatically repeating operations that may create duplicate transactions.
- Use idempotency support when provided by the backend for retryable operations.
15. OAuth 2.0 and OpenID Connect
OAuth 2.0 is an authorization framework. OpenID Connect adds an identity layer that supports user authentication. These standards are widely used by applications that need secure sign-in and access to protected APIs.
Recommended Practices for Native Android Applications
- Use a trusted identity provider and its supported Android SDK where possible.
- Use the Authorization Code flow with PKCE for native public clients when supported.
- Use the system browser or the provider-approved authentication experience.
- Do not embed a confidential client secret in a native application.
- Configure redirect URIs correctly.
- Request only the scopes required by the application.
- Validate tokens and claims according to the identity provider's requirements.
PKCE, or Proof Key for Code Exchange, helps protect the authorization-code exchange. It does not hide API keys inside an APK or replace secure token storage.
16. Protecting Credentials in Logs and Analytics
Credential leaks can occur through more than source code. Logcat output, crash reports, analytics events, screenshots, and diagnostic bundles may unintentionally expose sensitive information.
Safe Logging Practices
- Never log passwords, access tokens, refresh tokens, API secrets, or authorization headers.
- Do not place credentials in exception messages.
- Redact sensitive request information before sending diagnostics to third-party services.
- Log non-sensitive status messages instead.
- Review analytics properties to ensure they do not contain authentication data.
// Safer logging
Log.d("Authentication", "Token refresh completed")
// Never log the actual token or Authorization header.
17. Logout and Credential Revocation
Logging out should clear the application's local authentication state. Where supported, the application should also revoke refresh tokens or terminate the server-side session.
Clearing a local token does not automatically invalidate a stolen copy. Server-side revocation and expiration policies are important parts of session security.
Logout Checklist
- Clear locally stored access and refresh tokens.
- Clear in-memory authentication state.
- Remove user-specific cached data when appropriate.
- Revoke tokens or terminate the server session where supported.
- Stop authenticated background work that should no longer continue.
- Return the user to an unauthenticated screen.
- Ensure logout errors do not accidentally restore a local authenticated state.
18. Development, Staging, and Production Credentials
Use separate environments for development, testing, and production. This reduces the risk of test code or development credentials affecting real users and live services.
| Environment |
Purpose |
Security Practice |
| Development |
Feature development and debugging |
Use test accounts and restricted credentials |
| Staging |
Pre-release testing |
Restrict access and avoid real user data where possible |
| Production |
Live users and services |
Use strict access controls, monitoring, rotation, and secure secret management |
19. Network Security Best Practices
- Use HTTPS for all authentication and credential-bearing requests.
- Keep normal TLS certificate validation enabled.
- Use Android Network Security Configuration for domain-specific network policies when needed.
- Avoid broad cleartext-traffic exceptions in production.
- Send credentials only to the intended trusted API.
- Enforce access permissions on the backend for every protected operation.
- Never assume that hiding a button in the UI prevents unauthorized API access.
20. Common Problems and Troubleshooting
| Problem |
Possible Cause |
Recommended Solution |
| HTTP 401 Unauthorized |
Missing, expired, invalid, or malformed token |
Check the authentication flow and follow the provider's refresh or re-login rules |
| HTTP 403 Forbidden |
Insufficient permissions or scopes |
Check roles, scopes, account permissions, and API restrictions |
| API key fails in release builds |
Incorrect environment or signing-certificate restrictions |
Verify release configuration and provider restrictions |
| Token disappears after restart |
Token stored only in memory or persistence failure |
Review the intended session policy and secure storage implementation |
| Refresh requests keep failing |
Refresh token expired, revoked, or rotated incorrectly |
Review provider responses and require sign-in when necessary |
| Credentials appear in crash reports |
Sensitive headers or exception data are captured |
Redact credentials and review reporting configuration |
| API key exposed in APK |
Confidential key packaged in the client |
Rotate the key if needed, move confidential operations to a backend, and apply restrictions |
21. Practical Project: Secure Authentication Application
Build a simple Android application that allows users to sign in and view protected profile information. The application should demonstrate secure credential management and session handling.
Project Requirements
- Create a login screen with input validation.
- Authenticate users through a test backend or supported identity-provider SDK.
- Receive an access token using the approved authentication flow.
- Store sensitive tokens with the provider's recommended mechanism or an appropriate encrypted-storage solution.
- Attach the access token only to requests sent to the trusted API.
- Handle token expiration and refresh when supported.
- Handle unauthorized and forbidden responses correctly.
- Implement logout and clear local authentication state.
- Ensure logs and analytics never expose credentials.
- Test expired tokens, revoked sessions, network errors, and application restarts.
Suggested Project Structure
com.example.secureauth
├── data
│ ├── AuthApi.kt
│ ├── AuthRepository.kt
│ └── SecureTokenStore.kt
├── network
│ ├── ApiClient.kt
│ └── AuthHeaderInterceptor.kt
├── ui
│ ├── LoginScreen.kt
│ └── ProfileScreen.kt
└── MainActivity.kt
This structure is illustrative. Adapt it to the libraries and architecture used in your application. Test credential storage, refresh coordination, and network authorization independently.
22. Testing Checklist
- Confirm that confidential server-side secrets are not packaged in the APK.
- Check logs and crash reports for credential exposure.
- Verify that authentication requests use HTTPS.
- Confirm that tokens are sent only to the intended API host.
- Test access-token expiration and refresh behavior.
- Test invalid and revoked refresh tokens.
- Verify that logout clears local credentials and requests revocation where supported.
- Test simultaneous API requests when a token expires.
- Verify that backend permissions are enforced independently of the UI.
- Review API key restrictions, quotas, and monitoring.
23. Best Practices Summary
- Never package confidential server-side secrets inside an Android APK.
- Restrict client-side API keys when the provider supports restrictions.
- Use short-lived access tokens where supported.
- Protect refresh tokens carefully and use rotation or revocation when available.
- Prefer established authentication libraries and documented OAuth/OpenID Connect flows.
- Use Android Keystore as part of an appropriate cryptographic key-management strategy.
- Use encrypted storage for sensitive local data when required.
- Send credentials only over HTTPS to trusted endpoints.
- Never log credentials or include them in analytics events.
- Implement controlled refresh, logout, and revocation behavior.
- Enforce authorization on the backend, not only in the Android interface.
24. Interview Questions and Answers
Q1. What is an API key?
An API key is a value used by a service to identify an application or project and may be used for quotas, restrictions, or access control.
Q2. What is the difference between an access token and a refresh token?
An access token is used to access protected resources. A refresh token can be exchanged for a new access token when the authentication provider supports that process.
Q3. Why should confidential API keys not be hardcoded in Android applications?
Application packages can be inspected or reverse-engineered, so a hardcoded confidential key may be extracted and misused.
Q4. What is Android Keystore?
Android Keystore is a system for creating and using cryptographic keys with protections that can limit direct access to key material.
Q5. Why should authentication requests use HTTPS?
HTTPS encrypts communication in transit and helps protect credentials from interception when TLS is configured correctly.
Q6. What should an application do when an access token expires?
It should follow the provider's documented renewal flow, refresh the token when appropriate, and require authentication again if renewal fails.
Q7. Why should tokens not be logged?
Logs and diagnostic systems may expose credentials, allowing unauthorized parties to use them.
Q8. What is PKCE?
PKCE is an OAuth extension that helps protect authorization-code exchanges for public clients, including native mobile applications.
Q9. Does clearing a token from local storage revoke it?
No. Local deletion removes the application's copy but does not necessarily invalidate other copies. Server-side revocation or expiration may also be required.
Q10. Where should confidential third-party API secrets be stored?
They should generally be stored on a protected backend server or in a server-side secrets manager, not inside the Android application package.
25. Quick Revision Checklist
- API keys identify applications or projects.
- Access tokens authorize requests to protected resources.
- Refresh tokens can renew access when supported.
- Android Keystore protects cryptographic keys; it does not automatically encrypt arbitrary token strings.
- Confidential server secrets belong on the backend.
- HTTPS protects credentials in transit.
- Tokens should never be written to logs or analytics events.
- Refresh operations should be coordinated and retry limits enforced.
- Logout should clear local session data and revoke credentials when supported.
- Backend authorization must be enforced for every protected operation.
Conclusion
Managing API keys, tokens, and authentication credentials is a fundamental part of secure Android development. Developers must understand the purpose of each credential, store sensitive values appropriately, transmit them securely, and handle expiration, renewal, and logout correctly.
By using established authentication libraries, keeping confidential secrets on the backend, protecting sensitive local data, restricting API keys, and enforcing server-side authorization, developers can build Android applications that communicate with APIs more safely and reliably.
Learn more through the JustAcademy Android App Development Course, register for a course demo, or visit the JustAcademy website.